package wh.coach._thread;

/**
 * @author hangwen
 * @date 2023/10/21
 */
public class SyncDemo {
    public static void main(String[] args) {
        var o1 = new AType();
        var o2 = new AType();

        // 问题1：2个线程 分别调用o1.fun1，会不会有锁竞争
        new Thread(() -> {
            o1.fun1();
        }, "线程1").start();

        new Thread(() -> {
            o1.fun1();
        }, "线程2").start();
        //会有锁竞争，因为锁的是实例对象而两个都是访问的同一个实例（instance）对象fun1（）

        // 问题2：2个线程 一个调用o1.fun1,一个调用o2.fun1，会不会有锁竞争
        new Thread(() -> {
            o1.fun1();
        }, "线程3").start();

        new Thread(() -> {
            o2.fun1();
        }, "线程4").start();
        //不会有锁竞争，因为锁的是实例对象而两个访问的不是同一个实例（instance）

        // 问题3：2个线程 一个调用o1.fun1,一个调用o1.fun2，会不会有锁竞争
        new Thread(() -> {
            o1.fun1();
        }, "线程5").start();

        new Thread(() -> {
            o1.fun2();
        }, "线程6").start();
        //会有锁竞争，因为锁的是实例对象而两个都是访问的同一个实例（instance）

        // 问题4：2个线程 一个调用o1.fun1,一个调用o2.fun2，会不会有锁竞争
        new Thread(() -> {
            o1.fun1();
        }, "线程7").start();

        new Thread(() -> {
            o2.fun2();
        }, "线程8").start();
        //不会有锁竞争，因为锁的是实例对象而两个访问的不是同一个实例（instance）

        // 问题5：2个线程 一个调用o1.fun1,AType.fun3，会不会有锁竞争
        new Thread(() -> {
            o1.fun1();
        }, "线程9").start();

        new Thread(() -> {
            AType.fun3();
        }, "线程10").start();
        //    按理应该是会锁住，因为一个static是加的类锁而

        //-----------------------------------------------

        // 问题6：2个线程 分别调用AType.fun3，会不会有锁竞争
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                AType.fun3();
            }
        }, "线程11");
        thread.start();

        new Thread(() -> {
            AType.fun3();
        }, "线程12").start();
        //   按理也是会锁住，线程11和线程12会竞争同一个类锁，导致控制台输出的信息交错显示

        //-----------------------------------------------

        //问题7：2个线程 一个调用o1.fun1,一个调用o1.fun4，会不会有锁竞争
    }

    public static class AType {
        public synchronized static void fun3() {
            System.out.println(Thread.currentThread().getName() + " fun3 start");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " fun3 end");
        }

        public synchronized void fun1() {
            System.out.println(Thread.currentThread().getName() + " fun1 start");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " fun1 end");
        }

        public synchronized void fun2() {
            System.out.println(Thread.currentThread().getName() + " fun2 start");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " fun2 end");
        }

        public void fun4() {

        }
    }
}
